热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基址|都会_中断处理流程梳理

篇首语:本文由编程笔记#小编为大家整理,主要介绍了中断处理流程梳理相关的知识,希望对你有一定的参考价值。在之前的ARMv8-A的异常文章中提到,ARMv8-

篇首语:本文由编程笔记#小编为大家整理,主要介绍了中断处理流程梳理相关的知识,希望对你有一定的参考价值。


在之前的ARMv8-A的异常文章中提到,ARMv8-A将中断也当做一种异常,中断分为IRQ和FIQ

 

假设当前在EL0运行一个64位的应用程序,触发了一个EL0的IRQ中断,则处理器会做如下的操作


  • 将CPU的状态PSTATE保存到SPSR_EL1寄存器中,PC保存到ELR_EL1寄存器中
  • 跳到异常的处理函数处

则就会跳到ARM64对应的异常向量表

/*
* Exception vectors.
*/
.pushsection ".entry.text", "ax"

.align 11
ENTRY(vectors)
kernel_ventry 1, sync_invalid // Synchronous EL1t
kernel_ventry 1, irq_invalid // IRQ EL1t
kernel_ventry 1, fiq_invalid // FIQ EL1t
kernel_ventry 1, error_invalid // Error EL1t

kernel_ventry 1, sync // Synchronous EL1h
kernel_ventry 1, irq // IRQ EL1h
kernel_ventry 1, fiq_invalid // FIQ EL1h
kernel_ventry 1, error // Error EL1h

kernel_ventry 0, sync // Synchronous 64-bit EL0
kernel_ventry 0, irq // IRQ 64-bit EL0
kernel_ventry 0, fiq_invalid // FIQ 64-bit EL0
kernel_ventry 0, error // Error 64-bit EL0

#ifdef CONFIG_COMPAT
kernel_ventry 0, sync_compat, 32 // Synchronous 32-bit EL0
kernel_ventry 0, irq_compat, 32 // IRQ 32-bit EL0
kernel_ventry 0, fiq_invalid_compat, 32 // FIQ 32-bit EL0
kernel_ventry 0, error_compat, 32 // Error 32-bit EL0
#else
kernel_ventry 0, sync_invalid, 32 // Synchronous 32-bit EL0
kernel_ventry 0, irq_invalid, 32 // IRQ 32-bit EL0
kernel_ventry 0, fiq_invalid, 32 // FIQ 32-bit EL0
kernel_ventry 0, error_invalid, 32 // Error 32-bit EL0
#endif
END(vectors)

因为是EL0触发的异常,而且异常状态是IRQ,则会根据异常向量表的基址跳大EL0_irq处, kernel_ventry 0, irq // IRQ 64-bit EL0

el0_irq:
kernel_entry 0
el0_irq_naked:
enable_da_f

irq_handler
b ret_to_user
ENDPROC(el0_irq)

kernel_entry 0,其中kernel_entry是一个宏,此宏会保存当前的线程,也就是进程的寄存器

stp x0, x1, [sp, #16 * 0]
stp x2, x3, [sp, #16 * 1]
stp x4, x5, [sp, #16 * 2]
stp x6, x7, [sp, #16 * 3]
stp x8, x9, [sp, #16 * 4]
stp x10, x11, [sp, #16 * 5]
stp x12, x13, [sp, #16 * 6]
stp x14, x15, [sp, #16 * 7]
stp x16, x17, [sp, #16 * 8]
stp x18, x19, [sp, #16 * 9]
stp x20, x21, [sp, #16 * 10]
stp x22, x23, [sp, #16 * 11]
stp x24, x25, [sp, #16 * 12]
stp x26, x27, [sp, #16 * 13]
stp x28, x29, [sp, #16 * 14]

enable_da_f 这个在ARM处理器状态由描述,DAIF。这里是关闭IRQ中断

/* IRQ is the lowest priority flag, unconditionally unmask the rest. */
.macro enable_da_f
msr daifclr, #(8 | 4 | 1)
.endm

  • 跳转到irq_handler去处理中断
  • 当中断处理完毕后,就会通过ret_to_user返回到用户空间

/*
* Interrupt handling.
*/
.macro irq_handler
ldr_l x1, handle_arch_irq
mov x0, sp
irq_stack_entry
blr x1
irq_stack_exit
.endm

.text

  • 将handle_arch_irq设置到x1, 而handle_arch_irq就是上一篇在gic驱动中设置的。set_handle_irq(gic_handle_irq);
  • 从进程的内核栈切换到中断栈

.macro irq_stack_entry
mov x19, sp // preserve the original sp

/*
* Compare sp with the base of the task stack.
* If the top ~(THREAD_SIZE - 1) bits match, we are on a task stack,
* and should switch to the irq stack.
*/
ldr x25, [tsk, TSK_STACK]
eor x25, x25, x19
and x25, x25, #~(THREAD_SIZE - 1)
cbnz x25, 9998f

ldr_this_cpu x25, irq_stack_ptr, x26
mov x26, #IRQ_STACK_SIZE
add x26, x25, x26

/* switch to the irq stack */
mov sp, x26
9998:
.endm

其中irq_stack_ptr就是中断栈,每一个cpu都会存在一个中断栈的。

DEFINE_PER_CPU_ALIGNED(unsigned long [IRQ_STACK_SIZE/sizeof(long)], irq_stack);

static void init_irq_stacks(void)
int cpu;

for_each_possible_cpu(cpu)
per_cpu(irq_stack_ptr, cpu) = per_cpu(irq_stack, cpu);

当切换到中断栈之后,则会跳到handle_arch_irq,则就会跳到之前设置的gic_handle_irq中。

static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
u32 irqnr;

do
irqnr = gic_read_iar();

if (likely(irqnr > 15 && irqnr <1020) || irqnr >&#61; 8192)
int err;

uncached_logk(LOGK_IRQ, (void *)(uintptr_t)irqnr);
if (static_branch_likely(&supports_deactivate_key))
gic_write_eoir(irqnr);
else
isb();

err &#61; handle_domain_irq(gic_data.domain, irqnr, regs); //处理中断
if (err)
WARN_ONCE(true, "Unexpected interrupt received!\\n");
if (static_branch_likely(&supports_deactivate_key))
if (irqnr <8192)
gic_write_dir(irqnr);
else
gic_write_eoir(irqnr);


continue;

假设当前的中断类型是SPI&#xff0c;则会进入到hanle_domian_irq中去

int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
bool lookup, struct pt_regs *regs)
struct pt_regs *old_regs &#61; set_irq_regs(regs);
unsigned int irq &#61; hwirq;
int ret &#61; 0;

irq_enter();

#ifdef CONFIG_IRQ_DOMAIN
if (lookup)
irq &#61; irq_find_mapping(domain, hwirq);
#endif

/*
* Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible.
*/
if (unlikely(!irq || irq >&#61; nr_irqs))
ack_bad_irq(irq);
ret &#61; -EINVAL;
else
generic_handle_irq(irq);


irq_exit();
set_irq_regs(old_regs);
return ret;
#endif

  • irq_enter则是代表进入中断上下文
  • 然后根据hwirq和domain&#xff0c;其中此domain是root domain&#xff0c;则寻找到hwirq对应的softirq
  • 如果此softirq 属于非法irq&#xff0c;则发回bad ack
  • 否则调用generic_handle_irq函数
  • 当处理完毕后&#xff0c;会退出中断上下文

int generic_handle_irq(unsigned int irq)
struct irq_desc *desc &#61; irq_to_desc(irq);

if (!desc)
return -EINVAL;
generic_handle_irq_desc(desc);
return 0;

根据softirq 获取此中断的中断描述符&#xff0c;调用generic_handle_irq_desc去处理中断&#xff0c;后面会涉及到irq domain的知识了。后面详细说


推荐阅读
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Html5-Canvas实现简易的抽奖转盘效果
    本文介绍了如何使用Html5和Canvas标签来实现简易的抽奖转盘效果,同时使用了jQueryRotate.js旋转插件。文章中给出了主要的html和css代码,并展示了实现的基本效果。 ... [详细]
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
  • 本文介绍了在CentOS 6.4系统中更新源地址的方法,包括备份现有源文件、下载163源、修改文件名、更新列表和系统,并提供了相应的命令。 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • 本文介绍了使用Spark实现低配版高斯朴素贝叶斯模型的原因和原理。随着数据量的增大,单机上运行高斯朴素贝叶斯模型会变得很慢,因此考虑使用Spark来加速运行。然而,Spark的MLlib并没有实现高斯朴素贝叶斯模型,因此需要自己动手实现。文章还介绍了朴素贝叶斯的原理和公式,并对具有多个特征和类别的模型进行了讨论。最后,作者总结了实现低配版高斯朴素贝叶斯模型的步骤。 ... [详细]
  • Todayatworksomeonetriedtoconvincemethat:今天在工作中有人试图说服我:{$obj->getTableInfo()}isfine ... [详细]
author-avatar
mobiledu2502924293
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有